package com.cfuture08.eweb4j.jdbc.sql;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import com.cfuture08.eweb4j.cache.ORMConfigBeanCache;
import com.cfuture08.eweb4j.orm.config.bean.ORMConfigBean;
import com.cfuture08.eweb4j.orm.config.bean.Property;
import com.cfuture08.util.ReflectUtil;
import com.cfuture08.util.StringUtil;

/**
 * 生成插入语句
 * 
 * @author cfuture.aw
 * @since v1.a.0
 */
public class InsertSqlCreator<T> {
	private T[] ts;

	public InsertSqlCreator(T... ts) {
		this.ts = ts;
	}

	public String insert(String condition) {
		if (this.ts != null && this.ts.length > 0) {
			StringBuilder sb = new StringBuilder();
			for (T t : this.ts) {
				sb.append(this.makeSQL(t, condition));
			}
			return sb.toString();
		} else {
			return "";
		}
	}

	private String makeSQL(T t, String condition) {
		ORMConfigBean ormBean = ORMConfigBeanCache.get(t.getClass());
		String table = ormBean != null ? ormBean.getTable() : t.getClass()
				.getSimpleName();
		return String.format("INSERT INTO %s %s ;", table, condition);
	}

	public String[] create() throws Exception {
		return this.create(null);
	}

	public String[] create(String condition) throws Exception {
		String[] sqls = new String[ts.length];
		for (int index = 0; index < ts.length; ++index) {
			String sql = "INSERT INTO ${table} ${columns} VALUES ${values} ${condition} ;";
			String table = null;
			StringBuilder columns = new StringBuilder("(");
			StringBuilder values = new StringBuilder("(");
			T t = ts[index];
			try {
				ORMConfigBean ormBean = ORMConfigBeanCache.get(t.getClass());
				table = ormBean == null ? t.getClass().getSimpleName()
						: ormBean.getTable();
				if (ormBean == null) {
					ReflectUtil ru = new ReflectUtil(t);
					Field[] fields = ru.getFields();

					int lastIndex = fields.length - 1;
					for (int i = 0; i < lastIndex; ++i) {
						Field f = fields[i];
						String column = f.getName();
						String name = column;
						Class<?> clazz = f.getClass();
						columns.append(column).append(",");
						Object value = null;
						Method m = ru.getMethod("get"
								+ StringUtil.toUpCaseFirst(name));
						if (m != null) {
							value = m.invoke(t);
							if (Boolean.class.isAssignableFrom(clazz)) {
								value = "true".equals(value) ? "1" : "0";
							}
						}

						values.append("'").append(value).append("'")
								.append(",");
					}
					columns.append(fields[lastIndex].getName()).append(")");
					Object value = null;
					Method m = ru.getMethod("get"
							+ StringUtil.toUpCaseFirst(fields[lastIndex]
									.getName()));
					if (m != null) {
						value = m.invoke(t);
						if (value == null) {
							value = 0;
						}
					}
					values.append("'").append(value).append("'").append(")");

					sql = sql.replace("${table}", table);
					sql = sql.replace("${columns}", columns.toString());
					sql = sql.replace("${values}", values.toString());
					if (condition != null) {
						sql = sql
								.replace("${condition}", " WHERE " + condition);
					} else {
						sql = sql.replace("${condition}", "");
					}

					sqls[index] = sql;
				} else {
					List<Property> pList = ormBean.getProperty();
					if (pList != null) {
						ReflectUtil ru = new ReflectUtil(t);
						int lastIndex = pList.size() - 1;
						for (int i = 0; i < lastIndex; ++i) {
							Property p = pList.get(i);
							String column = p.getColumn();
							String name = p.getName();
							String type = p.getType();
							columns.append(column).append(",");
							Object value = null;
							Method m = ru.getMethod("get"
									+ StringUtil.toUpCaseFirst(name));
							if (m != null) {
								value = m.invoke(t);
								if ("boolean".equalsIgnoreCase(type)) {
									value = "true".equals(value) ? "1" : "0";
								} else if (boolean.class.isAssignableFrom(m
										.getReturnType())) {
									value = "true".equals(value) ? "1" : "0";
								}
							}

							values.append("'").append(value).append("'")
									.append(",");
						}
						columns.append(pList.get(lastIndex).getColumn())
								.append(")");
						Object value = null;
						Method m = ru.getMethod("get"
								+ StringUtil.toUpCaseFirst(pList.get(lastIndex)
										.getName()));
						if (m != null) {
							value = m.invoke(t);
							if (value == null) {
								value = 0;
							}
						}
						values.append("'").append(value).append("'")
								.append(")");
					}
					sql = sql.replace("${table}", table);
					sql = sql.replace("${columns}", columns.toString());
					sql = sql.replace("${values}", values.toString());
					if (condition != null) {
						sql = sql
								.replace("${condition}", " WHERE " + condition);
					} else {
						sql = sql.replace("${condition}", "");
					}

					sqls[index] = sql;
				}
			} catch (Exception e) {
				throw e;
			}

		}

		return sqls;
	}

	public T[] getTs() {
		return ts;
	}

	public void setTs(T[] ts) {
		this.ts = ts;
	}
}
